package com.qiwenshare.file.controller;

import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.qiwenshare.common.anno.MyLog;
import com.qiwenshare.common.result.RestResult;
import com.qiwenshare.common.util.DateUtil;
import com.qiwenshare.common.util.security.JwtUser;
import com.qiwenshare.common.util.security.SessionUtil;
import com.qiwenshare.file.aop.annotation.FileOperationAuthCheck;
import com.qiwenshare.file.api.IFileService;
import com.qiwenshare.file.api.IFiletransferService;
import com.qiwenshare.file.api.IUserFileService;
import com.qiwenshare.file.api.UserfileHistoryService;
import com.qiwenshare.file.component.FileDealComp;
import com.qiwenshare.file.component.InitData;
import com.qiwenshare.file.constant.FileOperationTypeEnum;
import com.qiwenshare.file.constant.OperationTypeEnum;
import com.qiwenshare.file.domain.UserFile;
import com.qiwenshare.file.domain.UserfileHistory;
import com.qiwenshare.file.dto.file.*;
import com.qiwenshare.file.io.QiwenFile;
import com.qiwenshare.file.service.StorageService;
import com.qiwenshare.file.util.QiwenFileUtil;
import com.qiwenshare.file.vo.file.FileListTreeVO;
import com.qiwenshare.file.vo.file.FileListVO;
import com.qiwenshare.file.vo.file.UploadFileVo;
import com.qiwenshare.ufop.factory.UFOPFactory;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

/**
 * @author MJ
 * @title qiwen-file
 * @date 2023/10/12 9:15
 * @description TODO
 */
@Tag(name = "portalFile", description = "该接口为文件接口，主要用来做一些文件的基本操作，如创建目录，删除，移动，复制等。")
@RestController
@Slf4j
@RequestMapping("/portalFile")
public class PortalFileController {


    @Resource
    IFiletransferService filetransferService;

    @Resource
    IFileService fileService;
    @Resource
    IUserFileService userFileService;
    @Resource
    FileDealComp fileDealComp;
    @Resource
    StorageService storageService;
    @Resource
    UFOPFactory ufopFactory;

    @Resource
    private UserfileHistoryService userfileHistoryService;


    public static final String CURRENT_MODULE = "文件传输接口";

    public static Executor executor = Executors.newFixedThreadPool(20);

    @FileOperationAuthCheck(operationType = FileOperationTypeEnum.UPLOAD)
    @Operation(summary = "上传文件", description = "真正的上传文件接口", tags = {"filetransfer"})
    @RequestMapping(value = "/uploadfile", method = RequestMethod.POST)
    @MyLog(operation = "上传文件", module = CURRENT_MODULE)
    @ResponseBody
    public RestResult<UploadFileVo> uploadFile(HttpServletRequest request, UploadFileDTO uploadFileDto) {

        JwtUser sessionUserBean = SessionUtil.getSession();

        String userFileId = filetransferService.uploadFile(request, uploadFileDto, sessionUserBean.getUserId());
        UploadFileVo uploadFileVo = new UploadFileVo();
        uploadFileVo.setUserFileId(userFileId);
        return RestResult.success().data(uploadFileVo);

    }

    @FileOperationAuthCheck(operationType = FileOperationTypeEnum.MODIFY)
    @Operation(summary = "文件重命名", description = "文件重命名", tags = {"file"})
    @RequestMapping(value = "/renamefile", method = RequestMethod.POST)
    @MyLog(operation = "文件重命名", module = CURRENT_MODULE)
    @ResponseBody
    public RestResult<String> renameFile(@RequestBody RenameFileDTO renameFileDto) {

        JwtUser sessionUserBean = SessionUtil.getSession();
        UserFile userFile = userFileService.getById(renameFileDto.getUserFileId());

        List<UserFile> userFiles = userFileService.selectUserFileByNameAndPath(renameFileDto.getFileName(), userFile.getFilePath(), sessionUserBean.getUserId());
        if (userFiles != null && !userFiles.isEmpty()) {
            return RestResult.fail().message("同名文件已存在");
        }

        LambdaUpdateWrapper<UserFile> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.set(UserFile::getFileName, renameFileDto.getFileName())
                .set(UserFile::getUploadTime, DateUtil.getCurrentTime())
                .eq(UserFile::getUserFileId, renameFileDto.getUserFileId());
        userFileService.update(lambdaUpdateWrapper);
        if (1 == userFile.getIsDir()) {
            List<UserFile> list = userFileService.selectUserFileByLikeRightFilePath(new QiwenFile(userFile.getFilePath(), userFile.getFileName(), true).getPath(), sessionUserBean.getUserId());

            for (UserFile newUserFile : list) {
                newUserFile.setFilePath(newUserFile.getFilePath().replaceFirst(new QiwenFile(userFile.getFilePath(), userFile.getFileName(), userFile.getIsDir() == 1).getPath(),
                        new QiwenFile(userFile.getFilePath(), renameFileDto.getFileName(), userFile.getIsDir() == 1).getPath()));
                userFileService.updateById(newUserFile);
            }
        }
        fileDealComp.uploadESByUserFileId(renameFileDto.getUserFileId());

        //记录历史
        userfileHistoryService.save(UserfileHistory.builder()
                .historyId(IdUtil.getSnowflakeNextIdStr())
                .userFileId(userFile.getUserFileId())
                .operationType(OperationTypeEnum.MODIFY_FILE_NAME.getType())
                .newFileName(renameFileDto.getFileName())
                .oldFileName(userFile.getFileName())
                .isDir(0)
                .createUserId(sessionUserBean.getUserId())
                .createTime(DateUtil.getCurrentTime())
                .build());

        return RestResult.success();
    }

    @FileOperationAuthCheck(operationType = FileOperationTypeEnum.MODIFY)
    @Operation(summary = "上传替换文件", description = "上传替换文件", tags = {"filetransfer"})
    @RequestMapping(value = "/uploadReplaceFile", method = RequestMethod.POST)
    @MyLog(operation = "上传文件", module = CURRENT_MODULE)
    @ResponseBody
    public RestResult<UploadFileVo> uploadReplaceFile(HttpServletRequest request, UploadReplaceFileDTO uploadFileDto) {

        JwtUser sessionUserBean = SessionUtil.getSession();

        filetransferService.uploadReplaceFile(request, uploadFileDto, sessionUserBean.getUserId());
        UploadFileVo uploadFileVo = new UploadFileVo();
        return RestResult.success().data(uploadFileVo);

    }


    @FileOperationAuthCheck(operationType = FileOperationTypeEnum.DOWNLOAD)
    @Operation(summary = "下载文件", description = "下载文件接口", tags = {"filetransfer"})
    @MyLog(operation = "下载文件", module = CURRENT_MODULE)
    @RequestMapping(value = "/downloadfile", method = RequestMethod.GET)
    public void downloadFile(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, DownloadFileDTO downloadFileDTO) {
//        Cookie[] cookieArr = httpServletRequest.getCookies();
//        String token = "";
//        if (cookieArr != null) {
//            for (Cookie cookie : cookieArr) {
//                if ("token".equals(cookie.getName())) {
//                    token = cookie.getValue();
//                }
//            }
//        }
//        boolean authResult = fileDealComp.checkAuthDownloadAndPreview(downloadFileDTO.getShareBatchNum(),
//                downloadFileDTO.getExtractionCode(),
//                token,
//                downloadFileDTO.getUserFileId(), null);
//        if (!authResult) {
//            log.error("没有权限下载！！！");
//            return;
//        }
        httpServletResponse.setContentType("application/force-download");// 设置强制下载不打开
        UserFile userFile = userFileService.getById(downloadFileDTO.getUserFileId());
        String fileName = "";
        if (userFile.getIsDir() == 1) {
            fileName = userFile.getFileName() + ".zip";
        } else {
            fileName = userFile.getFileName() + "." + userFile.getExtendName();

        }
        try {
            fileName = new String(fileName.getBytes("utf-8"), "ISO-8859-1");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        httpServletResponse.addHeader("Content-Disposition", "attachment;fileName=" + fileName);// 设置文件名

        filetransferService.downloadFile(httpServletResponse, downloadFileDTO);
    }

    @FileOperationAuthCheck(operationType = FileOperationTypeEnum.DOWNLOAD)
    @Operation(summary = "根据FileId下载文件", description = "根据FileId下载文件", tags = {"filetransfer"})
    @MyLog(operation = "下载文件", module = CURRENT_MODULE)
    @RequestMapping(value = "/downloadfileByFileId", method = RequestMethod.GET)
    public void downloadFileByFileId(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, DownloadFileDTO downloadFileDTO) {
//        Cookie[] cookieArr = httpServletRequest.getCookies();
//        String token = "";
//        if (cookieArr != null) {
//            for (Cookie cookie : cookieArr) {
//                if ("token".equals(cookie.getName())) {
//                    token = cookie.getValue();
//                }
//            }
//        }
//        boolean authResult = fileDealComp.checkAuthDownloadAndPreview(downloadFileDTO.getShareBatchNum(),
//                downloadFileDTO.getExtractionCode(),
//                token,
//                downloadFileDTO.getUserFileId(), null);
//        if (!authResult) {
//            log.error("没有权限下载！！！");
//            return;
//        }
        httpServletResponse.setContentType("application/force-download");// 设置强制下载不打开
        UserFile userFile = userFileService.getById(downloadFileDTO.getUserFileId());
        String fileName = "";
        if (userFile.getIsDir() == 1) {
            fileName = userFile.getFileName() + ".zip";
        } else {
            fileName = userFile.getFileName() + "." + userFile.getExtendName();

        }
        try {
            fileName = new String(fileName.getBytes("utf-8"), "ISO-8859-1");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        httpServletResponse.addHeader("Content-Disposition", "attachment;fileName=" + fileName);// 设置文件名

        filetransferService.downloadFileByFileId(httpServletResponse, downloadFileDTO);
    }

    @FileOperationAuthCheck(operationType = FileOperationTypeEnum.MODIFY)
    @Operation(summary = "创建文件夹", description = "目录(文件夹)的创建", tags = {"file"})
    @RequestMapping(value = "/createFold", method = RequestMethod.POST)
    @MyLog(operation = "创建文件夹", module = CURRENT_MODULE)
    @ResponseBody
    public RestResult<String> createFold(@Valid @RequestBody CreateFoldDTO createFoldDto) {

        String userId = SessionUtil.getSession().getUserId();
        String filePath = createFoldDto.getFilePath();


        boolean isDirExist = fileDealComp.isDirExist(createFoldDto.getFileName(), createFoldDto.getFilePath(), userId);

        if (isDirExist) {
            return RestResult.fail().message("同名文件夹已存在");
        }

        UserFile userFile = QiwenFileUtil.getQiwenDir(userId, filePath, createFoldDto.getFileName());

        userFileService.save(userFile);
        fileDealComp.uploadESByUserFileId(userFile.getUserFileId());
        //记录历史
        userfileHistoryService.save(UserfileHistory.builder()
                .historyId(IdUtil.getSnowflakeNextIdStr())
                .userFileId(userFile.getUserFileId())
                .operationType(OperationTypeEnum.ADD_FOLD.getType())
                .isDir(1)
                .createUserId(userId)
                .createTime(DateUtil.getCurrentTime())
                .build());
        return RestResult.success();
    }

    @FileOperationAuthCheck(operationType = FileOperationTypeEnum.DELETE)
    @Operation(summary = "批量删除文件", description = "批量删除文件", tags = {"file"})
    @RequestMapping(value = "/batchdeletefile", method = RequestMethod.POST)
    @MyLog(operation = "批量删除文件", module = CURRENT_MODULE)
    @ResponseBody
    public RestResult<String> deleteImageByIds(@RequestBody BatchDeleteFileDTO batchDeleteFileDto) {
        String userFileIds = batchDeleteFileDto.getUserFileIds();
        String[] userFileIdList = userFileIds.split(",");
        userFileService.update(new UpdateWrapper<UserFile>().lambda().set(UserFile::getDeleteFlag, 1).in(UserFile::getUserFileId, Arrays.asList(userFileIdList)));
        for (String userFileId : userFileIdList) {
            executor.execute(() -> {
                userFileService.deleteUserFile(userFileId, SessionUtil.getUserId());
            });

            fileDealComp.deleteESByUserFileId(userFileId);
        }
        return RestResult.success().message("批量删除文件成功");
    }

    @Operation(summary = "查询文件夹Tree", description = "查询文件夹Tree", tags = {"file"})
    @RequestMapping(value = "/dicTree", method = RequestMethod.GET)
    @ResponseBody
    public RestResult<FileListTreeVO> queryDicTree() {
        return RestResult.success().data(fileService.queryPortalDicTree());
    }

    @Operation(summary = "获取文件列表", description = "用来做前台列表展示", tags = {"file"})
    @RequestMapping(value = "/getfilelist", method = RequestMethod.GET)
    @ResponseBody
    public RestResult<FileListVO> getFileList(
            @Parameter(description = "文件类型", required = true) String fileType,
            @Parameter(description = "文件名称", required = false) String fileName,
            @Parameter(description = "文件模式", required = false) Integer fileMode,
            @Parameter(description = "文件路径", required = true) String filePath,
            @Parameter(description = "当前页", required = true) long currentPage,
            @Parameter(description = "页面数量", required = true) long pageCount) {
        IPage<FileListVO> fileList = null;
        if ("0".equals(fileType)) {
            fileList = userFileService.portalUserFileList(null, filePath, fileMode, currentPage, pageCount, fileName);
        } else {
            fileList = userFileService.getFileByFileType(Integer.valueOf(fileType), fileMode, currentPage, pageCount, SessionUtil.getSession().getUserId(), fileName);
        }

        List<FileListVO> fileListVOS = fileList.getRecords().stream().peek(f -> {
            f.setCreateUser(InitData.getStaffNameByUserId(String.valueOf(f.getUserId())));
        }).collect(Collectors.toList());
        fileList.setRecords(fileListVOS);
        return RestResult.success().dataList(fileList.getRecords(), fileList.getTotal());
    }
}
